package com.linsen.core.common.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.linsen.core.common.constant.WebConstant;

import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.*;

/**
 * 返回结果对象
 *
 * @author zhaoyong
 * @date 2023/02/27
 */
public final class Result extends JSONObject {
    private static final long serialVersionUID = 1L;
    public static final int CODE_SUCCESS = 200;
    public static final int CODE_ERROR = 500;
    public static final String MSG_SUCCESS = "ok";
    public static final String MSG_ERROR = "error";
    public static final String CODE_KEY = "code";
    public static final String MSG_KEY = "msg";
    public static final String DATA_KEY = "data";

    public Result() {
    }

    public Result(int code, String msg, Object data) {
        this.setCode(code);
        this.setMsg(msg);
        this.setData(data);
    }

    public Result(Map<String, ?> map) {
        this.setMap(map);
    }

    public Integer getCode() {
        return super.getInteger(CODE_KEY);
    }

    public String getMsg() {
        return super.getString(MSG_KEY);
    }

    public <T> T getData(Class<T> className) {
        return super.getObject(DATA_KEY, className);
    }

    public <T> T getData(TypeReference<T> type) {
        return super.getObject(DATA_KEY, type);
    }

    public Result setCode(int code) {
        super.put(CODE_KEY, code);
        return this;
    }

    public Result setMsg(String msg) {
        super.put(MSG_KEY, msg);
        return this;
    }

    public Result setData(Object data) {
        super.put(DATA_KEY, data);
        return this;
    }

    public Result set(String key, Object data) {
        super.put(key, data);
        return this;
    }

    public <T> T get(String key, Class<T> className) {
        return super.getObject(key, className);
    }

    public <T> T get(String key, TypeReference<T> type) {
        return super.getObject(key, type);
    }

    public Result setMap(Map<String, ?> map) {
        for (String key : map.keySet()) {
            super.put(key, map.get(key));
        }

        return this;
    }

    public boolean hasSuccess() {
        return Objects.equals(CODE_SUCCESS, this.getCode());
    }

    public boolean hasError() {
        return !this.hasSuccess();
    }

    public static Result ok() {
        return new Result(200, MSG_SUCCESS, null);
    }

    public static Result ok(String msg) {
        return new Result(CODE_SUCCESS, msg, null);
    }

    public static Result ok(String msg, Object data) {
        return new Result(CODE_SUCCESS, msg, data);
    }

    public static Result code(int code) {
        return new Result(code, null, null);
    }

    public static Result data(Object data) {
        return new Result(CODE_SUCCESS, MSG_SUCCESS, data);
    }

    public static Result error() {
        return new Result(CODE_ERROR, MSG_ERROR, null);
    }

    public static Result error(String msg) {
        return new Result(CODE_ERROR, msg, null);
    }

    public static Result error(String msg, Object data) {
        return new Result(CODE_ERROR, msg, data);
    }

    public static Result error(Exception e) {
        return new Result(CODE_ERROR, StrUtil.split(e.getMessage(), ":").get(0), null);
    }

    public static Result error(int code, Exception e) {
        return new Result(code, StrUtil.split(e.getMessage(), ":").get(0), null);
    }

    public static Result get(int code, String msg) {
        return new Result(code, msg, null);
    }

    public static Result get(int code, String msg, Object data) {
        return new Result(code, msg, data);
    }

    @Override
    public String toString() {
        return super.toJSONString();
    }
}